package com.cash.channel.svc.logic;


import com.cash.channel.api.model.repay.TermOption;
import com.cash.channel.api.model.repay.WdOrderInfoModel;
import com.cash.channel.svc.dao.ChannelInfoMapper;
import com.cash.channel.svc.dao.ThirdDictMappingMapper;
import com.cash.channel.svc.dao.ThirdIdMappingMapper;
import com.cash.channel.svc.model.*;
import com.alibaba.fastjson.JSON;
import com.cash.channel.api.exception.CashChannelException;
import com.cash.channel.api.model.user.ThirdIdModel;
import com.cash.channel.api.model.user.ThirdUserIdModel;
import com.cash.user.model.UserInfoResultModel;
import com.cash.user.service.UserService;
import com.geex.haneda.HanedaException;
import com.geex.haneda.model.api.ApiReqModel;
import com.geex.haneda.model.api.ApiResModel;
import com.geex.haneda.model.api.api00001.FileInfo;
import com.geex.haneda.model.api.api00001.UserQCDataModel;
import com.geex.haneda.model.api.api00004.BasicDataModel;
import com.geex.haneda.service.ApiService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import geex.core.service.LoanService;
import geex.core.service.ProductService;
import geex.core.service.model.emuns.ProductTypeEnum;
import geex.core.service.model.loan.Loan;
import geex.core.service.model.product.Product;
import geex.core.service.model.product.SearchProductRequest;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Condition;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class ThirdCommonLogic {

    @Autowired(required = false)
    private UserService userService;

    @Autowired(required = false)
    private OrderLogic orderLogic;

    @Autowired(required = false)
    private RepayLogic repayLogic;

    @Autowired
    private ChannelLogic channelLogic;

    @Autowired(required = false)
    private ThirdIdMappingMapper thirdIdMappingMapper;

    @Autowired
    private ThirdDictMappingMapper thirdDictMappingMapper;

    @Autowired
    private ChannelInfoMapper channelInfoMapper;

    @Autowired(required = false)
    private ApiService hanedaApiService;

    @Autowired
    private ProductService productService;

    @Autowired
    private LoanService loanService;

    public ThirdIdModel findThirdIdModelByThirdOrderId(String thirdOrderId, String channel) throws CashChannelException {
        try {
            ThirdIdMapping record = new ThirdIdMapping();
            record.setcThirdId(thirdOrderId);
            record.setcChannel(channel);
            ThirdIdMapping thirdIdMapping = thirdIdMappingMapper.selectOne(record);
            if (thirdIdMapping==null) {
                throw new Exception("订单号不存在:"+thirdOrderId);
            }
            ThirdIdModel thirdIdModel = new ThirdIdModel();
            BeanUtils.copyProperties(thirdIdMapping, thirdIdModel);
            return thirdIdModel;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("获取订单信息失败");
        }
    }

    public ThirdIdModel findThirdIdModelByWdId(String wdId, String channel) throws CashChannelException {
        try {
            ThirdIdMapping record = new ThirdIdMapping();
            record.setcWdId(wdId);
            record.setcChannel(channel);
            ThirdIdMapping thirdIdMapping = thirdIdMappingMapper.selectOne(record);
            if (thirdIdMapping==null) {
                throw new Exception("订单号不存在:"+wdId);
            }
            ThirdIdModel thirdIdModel = new ThirdIdModel();
            BeanUtils.copyProperties(thirdIdMapping, thirdIdModel);
            return thirdIdModel;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("获取订单信息失败");
        }
    }

    public ThirdIdModel findThirdIdModelByAppId(String appId, String channel) throws Exception {
        try {
            Condition condition = new Condition(ThirdIdMapping.class);
            condition.createCriteria().andEqualTo("cAppId", appId).andEqualTo("cChannel", channel);
            condition.orderBy("nId").desc();
            List<ThirdIdMapping> thirdIdMappings = thirdIdMappingMapper.selectByCondition(condition);
            if (thirdIdMappings.isEmpty()) {
                throw new Exception("订单号不存在:"+appId);
            }
            ThirdIdModel thirdIdModel = new ThirdIdModel();
            BeanUtils.copyProperties(thirdIdMappings.get(0), thirdIdModel);
            return thirdIdModel;
        } catch (Exception e) {
            throw e;
        }
    }

    public List<ThirdIdModel> findThirdIdModelByThirdUserId(String thirdUserId, String channel) throws Exception {
        try {
            ThirdIdMapping record = new ThirdIdMapping();
            record.setcThirdUserId(thirdUserId);
            record.setcChannel(channel);
            List<ThirdIdMapping> thirdIdMappings = thirdIdMappingMapper.select(record);
            if (thirdIdMappings.isEmpty()) {
                throw new Exception("用户不存在:"+thirdUserId);
            }
            List<ThirdIdModel> thirdIdModelList = Lists.newLinkedList();
            for (ThirdIdMapping thirdIdMapping: thirdIdMappings) {
                ThirdIdModel thirdIdModel = new ThirdIdModel();
                BeanUtils.copyProperties(thirdIdMapping, thirdIdModel);
                thirdIdModelList.add(thirdIdModel);
            }
            return thirdIdModelList;
        } catch (Exception e) {
            throw e;
        }
    }

    public void insertOrUpdateIdMapping(String thirdId, String channel, ThirdIdModel thirdIdModel) {
        ThirdIdMapping record = new ThirdIdMapping();
        record.setcThirdId(thirdId);
        record.setcChannel(channel);
        ThirdIdMapping thirdIdMapping = thirdIdMappingMapper.selectOne(record);
        if (thirdIdMapping == null) {
            thirdIdMapping = new ThirdIdMapping();
        }
        BeanUtils.copyProperties(thirdIdModel, thirdIdMapping,"nId");
        if (null == thirdIdMapping.getnId()) {
            thirdIdMapping.setdCreate(new Date());
            thirdIdMappingMapper.insertSelective(thirdIdMapping);
        } else {
            thirdIdMapping.setdUpdate(new Date());
            thirdIdMappingMapper.updateByPrimaryKeySelective(thirdIdMapping);
        }
    }

    public Map<String, Map<String, ThirdDictMapping>> findAllThirdDict(String channel) throws Exception {
        List<ThirdDictMapping> thirdDictModelList = findAllThirdDictModel(channel);
        Map<String, Map<String, ThirdDictMapping>> resultMap = Maps.newHashMap();
        Map<String, ThirdDictMapping> dictMap = null;
        for (ThirdDictMapping ThirdDictMapping: thirdDictModelList) {
            if ((dictMap = resultMap.get(ThirdDictMapping.getcThirdPcode()))==null){
                dictMap = Maps.newHashMap();
            }
            dictMap.put(ThirdDictMapping.getcThirdCode(), ThirdDictMapping);
            resultMap.put(ThirdDictMapping.getcThirdPcode(), dictMap);
        }
        return resultMap;
    }

    private List<ThirdDictMapping> findAllThirdDictModel(String channel) {
        Condition condition = new Condition(ThirdDictMapping.class);
        condition.createCriteria().andEqualTo("cChannel", channel);
        return thirdDictMappingMapper.selectByCondition(condition);
    }

    public ThirdDictMapping findThirdDictModelByThirdCodeAndThirdPCode(String pCode, String code, String channel) throws Exception {
        Condition condition = new Condition(ThirdDictMapping.class);
        condition.createCriteria().andEqualTo("cChannel", channel).andEqualTo("cThirdPcode", pCode).andEqualTo("cThirdCode", code);
        List<ThirdDictMapping> thirdDictMappingList = thirdDictMappingMapper.selectByCondition(condition);
        if (thirdDictMappingList.isEmpty()) {
            return null;
        }
        return thirdDictMappingList.get(0);
    }

    public ThirdDictMapping findThirdDictModelByOurCode(String pCode, String code, String channel) throws Exception {
        Condition condition = new Condition(ThirdDictMapping.class);
        condition.createCriteria().andEqualTo("cChannel", channel).andEqualTo("cPcode", pCode).andEqualTo("cCode", code);
        List<ThirdDictMapping> thirdDictMappingList = thirdDictMappingMapper.selectByCondition(condition);
        if (thirdDictMappingList.isEmpty()) {
            return null;
        }
        return thirdDictMappingList.get(0);
    }

    public BasicDataModel createBasicDataModelByOrderInfoModel(OrderInfoModel orderInfoModel) {
        BasicDataModel basicDataModel = new BasicDataModel();
        basicDataModel.setCMarital(orderInfoModel.getcMarriage());
        basicDataModel.setCEducation(orderInfoModel.getcScholarship());
        basicDataModel.setCHouseType(orderInfoModel.getUserAddressModel().getcHouseType());
        basicDataModel.setCHjAddress(orderInfoModel.getUserAddressModel().getcRegistryCity());
        basicDataModel.setCProvince(orderInfoModel.getUserAddressModel().getcProvince());
        basicDataModel.setCCity(orderInfoModel.getUserAddressModel().getcCity());
        basicDataModel.setCArea(orderInfoModel.getUserAddressModel().getcDistinct());
        basicDataModel.setCDetailAddr(orderInfoModel.getUserAddressModel().getcDetailAddress());
        basicDataModel.setCEmailAddr(orderInfoModel.getcEmail());
        basicDataModel.setCAddrCode(orderInfoModel.getUserAddressModel().getcAddrCode());
        basicDataModel.setCCpnyName(orderInfoModel.getUserJobModel().getcCpnyName());
        basicDataModel.setCCpnyProvince(orderInfoModel.getUserJobModel().getcCpnyProvince());
        basicDataModel.setCCpnyCity(orderInfoModel.getUserJobModel().getcCpnyCity());
        basicDataModel.setCCpnyArea(orderInfoModel.getUserJobModel().getcCpnyDistinct());
        basicDataModel.setCCpnyAddr(orderInfoModel.getUserJobModel().getcCpnyDetailAddress());
        basicDataModel.setCCpnyTel(orderInfoModel.getUserJobModel().getcCpnyTel());
        basicDataModel.setCCpnyWorkYear(orderInfoModel.getUserJobModel().getcAgeOfJob());
        basicDataModel.setCCpnyWorkType(orderInfoModel.getUserJobModel().getcJobType());
        basicDataModel.setCCpnyIncome1m(orderInfoModel.getUserJobModel().getcRangeOfSalary());
        basicDataModel.setCCpnyAddrCode(orderInfoModel.getUserJobModel().getcCpnyAddrCode());
        basicDataModel.setCRelation1(orderInfoModel.getUserContactModel().getcRelation1());
        basicDataModel.setCRelation2(orderInfoModel.getUserContactModel().getcRelation2());
        basicDataModel.setCContactMbl1(orderInfoModel.getUserContactModel().getcMobile1());
        basicDataModel.setCContactMbl2(orderInfoModel.getUserContactModel().getcMobile2());
        basicDataModel.setCContactName1(orderInfoModel.getUserContactModel().getcName1());
        basicDataModel.setCContactName2(orderInfoModel.getUserContactModel().getcName2());
        basicDataModel.setNIsLastCall(1);
        basicDataModel.setNChildNum(orderInfoModel.getcChildrenNumber());
        return basicDataModel;
    }

    public UserQCDataModel createUserQcDataModelByOrderInfoModel(OrderInfoModel orderInfoModel, String channel) throws CashChannelException {
        UserQCDataModel userQCDataModel = new UserQCDataModel();
        userQCDataModel.setCUuid(orderInfoModel.getcUid());
        userQCDataModel.setCName(orderInfoModel.getcName());
        userQCDataModel.setCIdno(orderInfoModel.getcIdno());
        userQCDataModel.setCMobile(orderInfoModel.getcMobile());
        userQCDataModel.setCIdnoValid(orderInfoModel.getcIdnoValid());
        userQCDataModel.setIsHasOperator(getChannelInfoByChannelCode(channel).getnOperatorStatus());
        List<FileInfo> fileInfos = Lists.newArrayList();
        FileInfo fileInfo = null;
        for (FileInfoModel fileInfoModel :orderInfoModel.getFileInfoModels()){
            fileInfo = new FileInfo();
            BeanUtils.copyProperties(fileInfoModel, fileInfo);
            fileInfo.setNType(Integer.parseInt(fileInfoModel.getnType()));
            fileInfos.add(fileInfo);
        }
        userQCDataModel.setFileInfo(fileInfos);
        return userQCDataModel;
    }

    public ChannelInfo getChannelInfoByChannelCode(String channelCode) throws CashChannelException {
        Condition condition = new Condition(ChannelInfo.class);
        condition.createCriteria().andEqualTo("cChannel", channelCode);
        List<ChannelInfo> channelInfoList = channelInfoMapper.selectByCondition(condition);
        if (channelInfoList.isEmpty()) {
            throw new CashChannelException("未找到渠道["+channelCode+"]");
        }
        return channelInfoList.get(0);
    }

    public ThirdUserIdModel getThirdUserInfo(String orderNo, String channel) {
        try {
            log.info("getThirdUserInfo...orderNo:{},channel:{}",orderNo,channel);
            ThirdUserIdModel thirdUserIdModel= new ThirdUserIdModel();


            ThirdIdModel thirdIdModel = thirdIdMappingMapper.getThirdIdByThirdIdAndChannel(orderNo,channel);
            if (thirdIdModel==null) {
                throw new Exception("订单号不存在:"+orderNo);
            }


            log.info("getThirdUserInfo..result"+thirdIdModel);
            if(null==thirdIdModel||null==thirdIdModel.getCUserUid()){
                throw new Exception("用户不存在!");
            }
            UserInfoResultModel userInfoModel=userService.getUserInfo(thirdIdModel.getCUserUid());
            if(null==userInfoModel){
                throw new Exception("用户不存在!");
            }
            thirdUserIdModel.setUserInfoModel(userInfoModel);
            thirdUserIdModel.setThirdIdModel(thirdIdModel);
            return thirdUserIdModel;
        }catch (Exception e){
            log.error("查询用户信息失败"+e.getMessage(),e);
        }
        return null;
    }
    /**
     * 审批提现前置条件
     *
     * @param uid
     * @param loanAmount
     * @return
     * @throws Exception
     */
    public Boolean checkOrderStatus(String uid, BigDecimal loanAmount) throws Exception {
        try {
            Map<String, Object> resultMap = orderLogic.secUsersOrderInfoAPI(uid);
            Integer NQCAppStatus = null;
            if (resultMap == null) {
                log.info("uid:{}审批提现前置条件:暂无有效认证记录", uid);
                return false;
            }
            BigDecimal surplusAmount = BigDecimal.ZERO;
            if (MapUtils.getInteger(resultMap, "nAppAmt") != null) {
                surplusAmount = new BigDecimal(MapUtils.getString(resultMap, "nAppAmt"));
            }
            if (MapUtils.getString(resultMap, "nQCAppStatus") != null) {
                NQCAppStatus = Integer.valueOf(MapUtils.getString(resultMap, "nQCAppStatus"));
            }
            if (300 != NQCAppStatus) {
                log.info("uid:{}审批提现前置条件:认证状态{}", uid, NQCAppStatus);
                return false;
            }
            List<WdOrderInfoModel> list = repayLogic.findAllWithdrawApplistByUid(uid, "");
            if (CollectionUtils.isNotEmpty(list)) {
                for (WdOrderInfoModel model : list) {

                    Loan loan = loanService.findLoanByExtId(model.getCWdAppId());
                    log.info("查询CWdAppId:{}核心还款计划{}：", model.getCWdAppId(), JSONObject.fromObject(loan));
                    if(loan==null){
                        if (model.getDInvalidTime() == null||(model.getDInvalidTime() != null && model.getDInvalidTime().compareTo(new Date()) >= 0)) {
                            log.info("uid:{}审批提现前置条件:提现订单:{}状态:{}", model.getCWdAppId(), uid, model.getNAppStatus());
                            return false;
                        }
                    }
                    if (loan.getOverdueDays() > 0) {
                        log.info("uid:{}审批提现前置条件:提现订单:{}逾期天数:{}", uid, model.getCWdAppId(), loan.getOverdueDays());
                        return false;
                    }

                    if (!("完成".equals(loan.getLoanStatus().name()) || "退货完成".equals(loan.getLoanStatus().name()) || "提前还款完成".equals(loan.getLoanStatus().name()))) {
                        surplusAmount = surplusAmount.subtract(model.getNWdAmt());
                    }
                }
            }
            if (loanAmount!=null&&surplusAmount.compareTo(loanAmount)<0){
                log.info("uid:{}审批提现前置条件:超过最大额度:{}", uid, surplusAmount);
                return false;
            }
            if (loanAmount!=null&&(surplusAmount.compareTo(new BigDecimal(1000)) < 0)) {
                log.info("uid:{}审批提现前置条件:剩余额度不足:{}", uid, surplusAmount);
                return false;
            }
        } catch (Exception e) {
            log.error("uid:{}审批提现前置条件查询失败:{}", uid, e.getMessage(), e);
            return false;
        }
        return true;
    }

    public Map<String, Object> do360IdentifiOrderAPI(Map<String, Object> do360IdentifiOrderAPIParams) throws CashChannelException {
        try {
            log.info("风控端：融360-认证订单生成接口:" + do360IdentifiOrderAPIParams);
            com.alibaba.fastjson.JSONObject requestObj = new com.alibaba.fastjson.JSONObject();
            requestObj.putAll(do360IdentifiOrderAPIParams);
            ApiResModel apiResModel = hanedaApiService.api(new ApiReqModel("do360IdentifiOrderAPI", requestObj.toString()));
            if (!apiResModel.getSuccess()) {
                log.error("风控端：融360-认证订单生成接口失败:" + JSON.toJSONString(do360IdentifiOrderAPIParams) + "\t" + apiResModel.getErrMessage());
                throw new HanedaException(apiResModel.getErrMessage());
            } else {
                Map<String, Object> resultMap = com.alibaba.fastjson.JSONObject.parseObject(apiResModel.getResult());
                log.info("风控端：融360-认证订单生成接口:" + apiResModel.getResult());
                return resultMap;
            }
        } catch (Exception ex) {
            log.error("风控端：融360-认证订单生成接口失败:" + JSON.toJSONString(do360IdentifiOrderAPIParams) + "\t" + ex.getMessage(), ex);
            throw new CashChannelException(ex.getMessage());
        }
    }

    public List<Product> getThirdProductInfoList(String channel) throws Exception {
        try {
            log.info("获取产品列表开始：" + channel);
            ChannelInfo channelInfo = channelLogic.getChannelInfoByCode(channel);
            log.info("获取channel对应产品组完成:" + "\t" + JSON.toJSONString(channelInfo));
            SearchProductRequest searchProductRequest = new SearchProductRequest();
            searchProductRequest.setProductType(ProductTypeEnum.XJD);
            searchProductRequest.setSetName(channelInfo.getcProductCode());
            searchProductRequest.setPage(1);
            List<Product> productList = productService.searchProduct(searchProductRequest);
            log.info("产品列表" + productList);
            if(null==productList){
                throw new Exception("未查询到对应的产品列表");
            }
            return productList;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            log.error("通过订单号获取产品信息异常", e);
            throw e;
        }
    }

    public List<TermOption> getLoanTermOption(String channel) throws CashChannelException {
        try {
            List<TermOption> termOptions = Lists.newLinkedList();
            List<Product> productList = getThirdProductInfoList(channel);
            for (Product product: productList) {
                termOptions.add(new TermOption(product.getId(), product.getProductName(), product.getTenor()));
            }
            return termOptions;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("获取期数产品失败");
        }

    }
}
